﻿
using Furion.RemoteRequest.Extensions;
using LocalNas.Application.Service.NasFile.Dto;
using LocalNas.Core.Const;
using System.Text.RegularExpressions;

namespace LocalNas.Application.Service;

[ApiDescriptionSettings(ConstSwaggerGroup.NAS平台, Name = "文件服务", Order = 100)]
public class NasFileService : IDynamicApiController, ITransient
{
    private readonly SqlSugarRepository<SysUserFolder> _sysUserFolderRep;
    public NasFileService(SqlSugarRepository<SysUserFolder> sysUserFolderRep)
    {
        _sysUserFolderRep = sysUserFolderRep;
    }

    /// <summary>
    /// 获取所有硬盘
    /// </summary>
    /// <returns></returns>
    [HttpGet("/NasFile/GetAllDiskByUser")]
    public async Task<List<GetAllDiskResult>> GetAllDiskByUser()
    {
        var allowPathList = await GetMyFolder();
        var diskList = _GetAllDisk()
            .WhereIF(allowPathList != null, x => allowPathList.Select(x => x.Path).Contains(x.Path))
            .ToList();
        return diskList;
    }

    /// <summary>
    /// 获取所有硬盘
    /// </summary>
    /// <returns></returns>
    [HttpGet("/NasFile/GetAllDisk")]
    public List<GetAllDiskResult> GetAllDisk()
    {
        return _GetAllDisk();
    }

    /// <summary>
    ///  
    /// </summary>
    /// <returns></returns>
    [HttpPost("/NasFile/GetFolderTree")]
    public dynamic GetFolderTree(DirectoryContentsReuqest request)
    {
        var path = request.Path;
        var fileProvider = FS.GetPhysicalFileProvider(path);
        var fileinfos = fileProvider.GetDirectoryContents("");
        try
        {
            //遍历一下  如果没有权限会触发异常
            var list = fileinfos.ToList();
        }
        catch (Exception ex)
        {
            throw Oops.Oh(ex.Message);
        }
        return fileinfos.Where(x => x.IsDirectory).Select(x => new
        {
            Path = x.PhysicalPath
        }).ToList();
    }



    private async Task<List<SysUserFolder>> GetMyFolder()
    {
        //根据用户ID 限制
        long.TryParse(App.User.FindFirst(ClaimConst.UserId)?.Value, out long userId);
        List<SysUserFolder> allowPathList = null;
        if (App.User.FindFirst(ClaimConst.UserType)?.Value != UserTypeEnum.超级管理员.ToInt().ToString())
        {
            //超管跳过
            allowPathList = await _sysUserFolderRep.AsQueryable().Where(x => x.UserId == userId)
                .ToListAsync();
        }
        return allowPathList;
    }

    private List<GetAllDiskResult> _GetAllDisk()
    {
        var diskList = DriveInfo.GetDrives()
        .Where(x => (x.DriveType == DriveType.Fixed || x.DriveType == DriveType.Removable || x.DriveType == DriveType.Network) && x.IsReady)
        .ToList()
        .Select(x => new GetAllDiskResult
        {
            Path = x.Name,
            Label = x.VolumeLabel,
            Root = true,
            PhysicalPath = x.Name,
            Key = x.Name,
            DriveType = x.DriveType.ToString(),
            DriveFormat = x.DriveFormat,
            TotalFreeSpace = x.TotalFreeSpace,
            TotalSize = x.TotalSize
        }).ToList();
        return diskList;
    }

    /// <summary>
    /// 获取路径内的所有文件或目录
    /// </summary>
    /// <param name="request"></param>
    /// <returns></returns>
    [HttpPost("/NasFile/GetDirectoryContents")]
    public async Task<GetDirectoryContentsResult> GetDirectoryContents(DirectoryContentsReuqest request)
    {
        //根据用户ID 限制 
        var allowPathList = await GetMyFolder();
        var path = request.Path;
        var fileProvider = FS.GetPhysicalFileProvider(path);

        var fileinfos = fileProvider.GetDirectoryContents("");
        try
        {
            //遍历一下  如果没有权限会触发异常
            var list = fileinfos.ToList();
        }
        catch (Exception ex)
        {
            throw Oops.Oh(ex.Message);
        }

        // 所有文件和目录  根据用户目录筛选或者根据父级目录包含
        var datas = fileinfos.WhereIF(allowPathList != null, x =>
        allowPathList.Select(y => y.Path).Contains(x.PhysicalPath)
        || allowPathList.Where(y => !y.Half).Any(y => x.PhysicalPath.StartsWith(y.Path))
        ).ToList();
        return new GetDirectoryContentsResult
        {
            FileInfos = datas,
            Path = path
        };


    }

    /// <summary>
    /// 新建目录
    /// </summary>
    /// <param name="request"></param>
    [HttpPost("/NasFile/CreateDirectory")]
    public void CreateDirectory(DirectoryContentsReuqest request)
    {
        if (!Directory.Exists(request.Path))
        {
            Directory.CreateDirectory(request.Path);
        }
    }

    /// <summary>
    /// 删除目录或者文件
    /// </summary>
    [HttpPost("/NasFile/DeleteDirectoryContent")]
    public void DeleteDirectoryContent(DeleteDirectoryContentRequest request)
    {
        if (request.IsDirectory)
        {
            Directory.Delete(request.Path, true);
        }
        else
        {
            if (!File.Exists(request.Path)) throw Oops.Oh("文件不存在，刷新后再试");
            File.Delete(request.Path);
        }
    }

    /// <summary>
    /// 重命名文件夹或者文件
    /// </summary>
    /// <param name="request"></param>
    [HttpPost("/NasFile/RenameDirectoryContents")]
    public void RenameDirectoryContents(RenameDirectoryContentsRequest request)
    {
        var oldPath = Path.Combine(request.Path, request.OldName);
        var newPath = Path.Combine(request.Path, request.NewName);
        if (request.IsDirectory)
        {
            Directory.Move(oldPath, newPath);
        }
        else
        {
            if (!File.Exists(oldPath)) throw Oops.Oh("文件不存在，刷新后再试");
            var file = new FileInfo(oldPath);
            file.MoveTo(newPath);
        }
    }


    [DisableRequestSizeLimit]
    [HttpGet("/NasFile/FileDownload"), NonUnify]
    public IActionResult FileDownload([FromQuery] FileDownloadRequest request)
    {
        var filePath = request.Path;
        var fileName = new Regex(@"[^\/\\]+$").Match(filePath).Value;
        return new FileStreamResult(new FileStream(filePath, FileMode.Open, FileAccess.Read, FileShare.Read), "application/octet-stream")
        {
            FileDownloadName = fileName// 配置文件下载显示名
        };
    }

    [AllowAnonymous]
    [DisableRequestSizeLimit]
    [HttpGet("/NasFile/FileLink"), NonUnify]
    public IActionResult FileLink([FromQuery] FileDownloadRequest request)
    {
        var filePath = request.Path;
        var fileName = new Regex(@"[^\/\\]+$").Match(filePath).Value;
        var result = new FileStreamResult(new FileStream(filePath, FileMode.Open, FileAccess.Read, FileShare.Read), "application/octet-stream")
        {
            FileDownloadName = fileName,// 配置文件下载显示名

        };
        if (App.HttpContext.Request.Headers.ContainsKey("Range"))
            result.EnableRangeProcessing = true;
        return result;
    }

    /// <summary>
    /// 上传文件
    /// </summary>
    /// <param name="request"></param>
    /// <returns></returns>
    [HttpPost("/NasFile/UploadFile"), NonUnify]
    public async Task UploadFile([FromForm] UploadFileReuqest request)
    {
        var fileName = request.File.FileName;
        var filePath = Path.Combine(request.Path, fileName);
        if (File.Exists(filePath)) throw Oops.Oh("文件已存在，禁止覆盖");
        // 保存到指定路径
        using (var stream = File.Create(filePath))
        {
            await request.File.CopyToAsync(stream);
        }
    }

    [HttpPost("/NasFile/DownloadTelegra")]
    public async Task DownloadTelegra(DownloadTelegraReuqest request)
    {
        var html = await request.Url.GetAsStringAsync();
        var title = new Regex("(?<=twitter:title\" content=\").*?(?=\")").Match(html).Value;
        var path = Path.Combine(request.Path, title);
        if (!Directory.Exists(path))
        {
            Directory.CreateDirectory(path);
        }

        var imgs = new Regex("(?<=img src=\").*?(?=\")", RegexOptions.Singleline).Matches(html);
        var list = imgs.Select(x => $"https://telegra.ph{x.Value}").ToList();
        var i = 1;
        foreach (var item in list)
        {
            var result = await item.GetAsStreamAsync();
            var _path = Path.Combine(path, $"{i:000}.jpg");
            using (var fileStream = File.Create(_path))
            {
                await result.Stream.CopyToAsync(fileStream);
            }
            i += 1;
        }
    }
}

